#include <stdio.h>
#include <math.h>

//二分法所使用的函数，传入参数为变量，返回值为函数值
double function1(double x){
    return pow(x,4)+2* pow(x,2)-x-4;
}
//迭代法所使用的函数，传入参数为变量，返回值为函数值
double function2(double x){
    return sqrt(sqrt(x+4-2*x*x));
}

/*
 * 二分法求根
 * 参数一：区间小值
 * 参数二：区间大值
 * 参数三：要求的精度
 * 参数四：二分法所用到的函数
 * 返回值：满足精度的根值
 */
double BiSearchForAns(double low,double high,double precision,double function(double x)){
    double preAns,nowAns,midX;  //用于保存上一次的答案，现在的答案，还有区间中点值
    midX=(high-low)/2+low;  //求区间中点
    nowAns=midX;    //设定现在的答案初值为区间中间

    //循环，直到满足精度需求
    while (fabs(high-low)/2>precision){
        double ret= function(midX); //获取区间中点的函数值
        if(function(high)*ret<0){  //如果f（x）*f（b）<0
            low=midX;
            midX=(high-midX)/2+midX;
        } else{ //如果f（x）*f（a）<0
            high=midX;
            midX=(midX-low)/2+low;
        }
        preAns=nowAns;  //将现在的答案值存放
        nowAns=midX;    //更新现在的答案值
//        printf("%.7f\n",nowAns);
//        printf("low=%.7f high=%.7f\n",low,high);
    }
//    printf("\n");
    return nowAns;
}

/*
 * 迭代法求根
 * 参数一：启动点
 * 参数二：要求的精度
 * 参数三：迭代所用的函数
 * 返回值：满足精度需求的根值
 */
double IterationForAns(double beginPoint,double precision,double function(double x)){
    double q=0.5681732712;  //手动求导得来的q值
    double preAns=0,nowAns=0;   //同上
    int flag=1; //用于检测是否是第一个进入循环
    while (((1/(1-q))* fabs(preAns-nowAns))>precision||flag){
        if(flag){   //如果是第一次进入循环
            preAns=beginPoint;  //设置上一次答案的初值
            nowAns=function(beginPoint);    //获取启动点的函数值，并将之作为现在的答案
            flag=0; //将第一次进入循环的标记清除
        } else{     //不是第一次进入循环
            preAns=nowAns;  //存放现在的答案
            nowAns=function(nowAns);    //获取当前答案的函数值作为当前答案，即迭代
        }
//        printf("preAns=%.7f nowAns=%.7f\n",preAns,nowAns);
    }
    return nowAns;
}


int main() {
//    printf("%.7f\n", BiSearchForAns(1,1.5,5e-6,function1));
    printf("%.7f\n", IterationForAns(1.25,5e-6,function2));

    return 0;
}
